#include "Arena.h"

#include <glm\gtc\matrix_transform.hpp>
#include <Bezier2D.h>

Arena::Arena() : 
	m_superficieUno( std::unique_ptr<Algoritmo2D>( new Bezier2D(3, 3) ) ),
	m_superficieDos( std::unique_ptr<Algoritmo2D>( new Bezier2D(4, 4) ) )
{
	std::vector< glm::vec3 > vec1;
	vec1.push_back( glm::vec3(1.0f, -1.0f, -0.01f) );
	vec1.push_back( glm::vec3(1.0f, 0.0f, 0.0f) );
	vec1.push_back( glm::vec3(1.0f, 1.0f, -0.01f) );

	std::vector< glm::vec3 > vec2;
	vec2.push_back( glm::vec3(0.0f, -1.5f, 0.0f) );
	vec2.push_back( glm::vec3(0.0f, 0.0f, 8.0f) );
	vec2.push_back( glm::vec3(0.0f, 1.5f, 0.0f) );

	std::vector< glm::vec3 > vec3;
	vec3.push_back( glm::vec3(-1.0f, -1.0f, -0.01f) );
	vec3.push_back( glm::vec3(-1.0f, 0.0f, 0.0f) );
	vec3.push_back( glm::vec3(-1.0f, 1.0f, -0.01f) );

	this->m_superficieUno.addCurvaControl( vec3 );
	this->m_superficieUno.addCurvaControl( vec2 );
	this->m_superficieUno.addCurvaControl( vec1 );

	// 
	vec1.clear();
	vec1.push_back( glm::vec3(1.0f, -2.0f, -0.01f) );
	vec1.push_back( glm::vec3(2.0f, -1.0f, 0.0f) );
	vec1.push_back( glm::vec3(2.0f, 1.0f, 0.0f) );
	vec1.push_back( glm::vec3(1.0f, 2.0f, -0.01f) );

	vec2.clear();
	vec2.push_back( glm::vec3(0.25f, -2.25f, 0.0f) );
	vec2.push_back( glm::vec3(1.0f, -0.5f, 2.0f) );
	vec2.push_back( glm::vec3(1.0f, 0.5f, 2.0f) );
	vec2.push_back( glm::vec3(0.25f, 2.25f, 0.0f) );

	vec3.clear();
	vec3.push_back( glm::vec3(-0.25f, -2.25f, 0.0f) );
	vec3.push_back( glm::vec3(-1.0f, -0.5f, 2.0f) );
	vec3.push_back( glm::vec3(-1.0f, 0.5f, 2.0f) );
	vec3.push_back( glm::vec3(-0.25f, 2.25f, 0.0f) );

	std::vector< glm::vec3 > vec4;
	vec4.push_back( glm::vec3(-1.0f, -2.0f, -0.01f) );
	vec4.push_back( glm::vec3(-2.0f, -1.0f, 0.0f) );
	vec4.push_back( glm::vec3(-2.0f, 1.0f, 0.0f) );
	vec4.push_back( glm::vec3(-1.0f, 2.0f, -0.01f) );

	this->m_superficieDos.addCurvaControl( vec4 );
	this->m_superficieDos.addCurvaControl( vec3 );
	this->m_superficieDos.addCurvaControl( vec2 );
	this->m_superficieDos.addCurvaControl( vec1 );
}


void Arena::init(const glm::vec3 &DireccionLuz, std::string vertShaderFileName, std::string fragShaderFileName) {
	this->m_superficieUno.buildCurva(12, 12);
	this->m_superficieDos.buildCurva(16, 16);

	Renderizable::init(DireccionLuz, vertShaderFileName, fragShaderFileName);
	Renderizable::setMaterial( glm::vec3(0.953f, 0.871f, 0.694f), glm::vec3(0.317f, 0.29f, 0.231f), glm::vec3(0.47f, 0.425f, 0.35f), 16.0f );
	Renderizable::setTextura("Arena-1.dds");
}


void Arena::renderizar(const glm::mat4 &matVista, const glm::mat4 &matProyeccion, const glm::mat4 &matModelo) const {
	// Carga el shader
	const GLuint shaderProgramID = Renderizable::cargarShaderProgram();

	// Empieza a dibujar todo
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	// Las matrices de transformacion, iluminacion y textura
	Renderizable::cargarMatricesTransformacion(matVista, matProyeccion, matModelo);
	Renderizable::cargarDatosIluminacion(matModelo, matVista);
	Renderizable::cargarTextura();

	// Los datos de las superficies
	std::vector< glm::vec3 > vecVertices = this->m_superficieUno.getVertices();
	std::vector< glm::vec3 > vecNormales = this->m_superficieUno.getNormales();
	std::vector< glm::vec2 > vecCoordsTextura = this->m_superficieUno.getCoordenadasTextura();
	std::vector< unsigned int > vecIndexBuffer = this->m_superficieUno.getIndexBuffer();

	glVertexPointer(3, GL_FLOAT, 0, &vecVertices[0]);
	glNormalPointer(GL_FLOAT, 0, &vecNormales[0]);
	glTexCoordPointer(2, GL_FLOAT, 0, &vecCoordsTextura[0]);
	glDrawElements(GL_TRIANGLES, vecIndexBuffer.size(), GL_UNSIGNED_INT, &vecIndexBuffer[0]);

	// Corro la segunda superficie respecto del centro
	glm::mat4 matMover = glm::translate( matModelo, glm::vec3(0.0f, 0.75f, 0.0f));
	const GLint locModelMatrix = glGetUniformLocation(shaderProgramID, "modelMatrix");
	if (locModelMatrix != -1)  glUniformMatrix4fv(locModelMatrix, 1, GL_FALSE, &matMover[0][0]);

	vecVertices = this->m_superficieDos.getVertices();
	vecNormales = this->m_superficieDos.getNormales();
	vecIndexBuffer = this->m_superficieDos.getIndexBuffer();
	vecCoordsTextura = this->m_superficieDos.getCoordenadasTextura();

	glVertexPointer(3, GL_FLOAT, 0, &vecVertices[0]);
	glNormalPointer(GL_FLOAT, 0, &vecNormales[0]);
	glTexCoordPointer(2, GL_FLOAT, 0, &vecCoordsTextura[0]);
	glDrawElements(GL_TRIANGLES, vecIndexBuffer.size(), GL_UNSIGNED_INT, &vecIndexBuffer[0]);

	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
}



